<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" lang="" xml:lang="">
<head>

  <meta charset="utf-8" />
  <meta http-equiv="X-UA-Compatible" content="IE=edge" />
  <title>2 为什么使用以及怎么使用 | Tidy evaluation</title>
  <meta name="description" content="这本书的目的是让你跟上 tidy evaluation 的进度，以及如何围绕 tidyverse 流程和语法编写函数" />
  <meta name="generator" content="bookdown 0.11 and GitBook 2.6.7" />

  <meta property="og:title" content="2 为什么使用以及怎么使用 | Tidy evaluation" />
  <meta property="og:type" content="book" />
  
  
  <meta property="og:description" content="这本书的目的是让你跟上 tidy evaluation 的进度，以及如何围绕 tidyverse 流程和语法编写函数" />
  <meta name="github-repo" content="ShixiangWang/tidyeval-chinese" />

  <meta name="twitter:card" content="summary" />
  <meta name="twitter:title" content="2 为什么使用以及怎么使用 | Tidy evaluation" />
  
  <meta name="twitter:description" content="这本书的目的是让你跟上 tidy evaluation 的进度，以及如何围绕 tidyverse 流程和语法编写函数" />
  

<meta name="author" content="Lionel Henry" />
<meta name="author" content="Hadley Wickham" />
<meta name="author" content="王诗翔（译）" />



  <meta name="viewport" content="width=device-width, initial-scale=1" />
  <meta name="apple-mobile-web-app-capable" content="yes" />
  <meta name="apple-mobile-web-app-status-bar-style" content="black" />
  
  
<link rel="prev" href="section-1.html">
<link rel="next" href="sec-do-you-need.html">
<script src="libs/jquery-2.2.3/jquery.min.js"></script>
<link href="libs/gitbook-2.6.7/css/style.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-table.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-bookdown.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-highlight.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-search.css" rel="stylesheet" />
<link href="libs/gitbook-2.6.7/css/plugin-fontsettings.css" rel="stylesheet" />







<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=UA-115082821-1"></script>
<script>
  window.dataLayer = window.dataLayer || [];
  function gtag(){dataLayer.push(arguments);}
  gtag('js', new Date());

  gtag('config', 'UA-115082821-1');
</script>


<style type="text/css">
a.sourceLine { display: inline-block; line-height: 1.25; }
a.sourceLine { pointer-events: none; color: inherit; text-decoration: inherit; }
a.sourceLine:empty { height: 1.2em; }
.sourceCode { overflow: visible; }
code.sourceCode { white-space: pre; position: relative; }
div.sourceCode { margin: 1em 0; }
pre.sourceCode { margin: 0; }
@media screen {
div.sourceCode { overflow: auto; }
}
@media print {
code.sourceCode { white-space: pre-wrap; }
a.sourceLine { text-indent: -1em; padding-left: 1em; }
}
pre.numberSource a.sourceLine
  { position: relative; left: -4em; }
pre.numberSource a.sourceLine::before
  { content: attr(data-line-number);
    position: relative; left: -1em; text-align: right; vertical-align: baseline;
    border: none; pointer-events: all; display: inline-block;
    -webkit-touch-callout: none; -webkit-user-select: none;
    -khtml-user-select: none; -moz-user-select: none;
    -ms-user-select: none; user-select: none;
    padding: 0 4px; width: 4em;
    color: #aaaaaa;
  }
pre.numberSource { margin-left: 3em; border-left: 1px solid #aaaaaa;  padding-left: 4px; }
div.sourceCode
  {  }
@media screen {
a.sourceLine::before { text-decoration: underline; }
}
code span.al { color: #ff0000; font-weight: bold; } /* Alert */
code span.an { color: #60a0b0; font-weight: bold; font-style: italic; } /* Annotation */
code span.at { color: #7d9029; } /* Attribute */
code span.bn { color: #40a070; } /* BaseN */
code span.bu { } /* BuiltIn */
code span.cf { color: #007020; font-weight: bold; } /* ControlFlow */
code span.ch { color: #4070a0; } /* Char */
code span.cn { color: #880000; } /* Constant */
code span.co { color: #60a0b0; font-style: italic; } /* Comment */
code span.cv { color: #60a0b0; font-weight: bold; font-style: italic; } /* CommentVar */
code span.do { color: #ba2121; font-style: italic; } /* Documentation */
code span.dt { color: #902000; } /* DataType */
code span.dv { color: #40a070; } /* DecVal */
code span.er { color: #ff0000; font-weight: bold; } /* Error */
code span.ex { } /* Extension */
code span.fl { color: #40a070; } /* Float */
code span.fu { color: #06287e; } /* Function */
code span.im { } /* Import */
code span.in { color: #60a0b0; font-weight: bold; font-style: italic; } /* Information */
code span.kw { color: #007020; font-weight: bold; } /* Keyword */
code span.op { color: #666666; } /* Operator */
code span.ot { color: #007020; } /* Other */
code span.pp { color: #bc7a00; } /* Preprocessor */
code span.sc { color: #4070a0; } /* SpecialChar */
code span.ss { color: #bb6688; } /* SpecialString */
code span.st { color: #4070a0; } /* String */
code span.va { color: #19177c; } /* Variable */
code span.vs { color: #4070a0; } /* VerbatimString */
code span.wa { color: #60a0b0; font-weight: bold; font-style: italic; } /* Warning */
</style>

<link rel="stylesheet" href="adv-r.css" type="text/css" />
</head>

<body>



  <div class="book without-animation with-summary font-size-2 font-family-1" data-basepath=".">

    <div class="book-summary">
      <nav role="navigation">

<ul class="summary">
<li><strong><a href="./">Tidy evaluation</a></strong></li>

<li class="divider"></li>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html"><i class="fa fa-check"></i>欢迎</a><ul>
<li class="chapter" data-level="" data-path="index.html"><a href="index.html#e585b6e4bb96e8b584e6ba90"><i class="fa fa-check"></i>其他资源</a></li>
</ul></li>
<li class="part"><span><b>I 原理</b></span></li>
<li class="chapter" data-level="1" data-path="section-1.html"><a href="section-1.html"><i class="fa fa-check"></i><b>1</b> 介绍</a></li>
<li class="chapter" data-level="2" data-path="sec-why-how.html"><a href="sec-why-how.html"><i class="fa fa-check"></i><b>2</b> 为什么使用以及怎么使用</a><ul>
<li class="chapter" data-level="2.1" data-path="sec-why-how.html"><a href="sec-why-how.html#section-2.1"><i class="fa fa-check"></i><b>2.1</b> 数据隐藏</a></li>
<li class="chapter" data-level="2.2" data-path="sec-why-how.html"><a href="sec-why-how.html#section-2.2"><i class="fa fa-check"></i><b>2.2</b> 引用代码</a></li>
<li class="chapter" data-level="2.3" data-path="sec-why-how.html"><a href="sec-why-how.html#section-2.3"><i class="fa fa-check"></i><b>2.3</b> 去引用代码</a></li>
</ul></li>
<li class="chapter" data-level="3" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html"><i class="fa fa-check"></i><b>3</b> 你需要 tidy eval 吗？</a><ul>
<li class="chapter" data-level="3.1" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#sec:fixed-colnames"><i class="fa fa-check"></i><b>3.1</b> 固定列名</a></li>
<li class="chapter" data-level="3.2" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#sec:automating-loops"><i class="fa fa-check"></i><b>3.2</b> 自动循环</a><ul>
<li class="chapter" data-level="3.2.1" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#dplyr-"><i class="fa fa-check"></i><b>3.2.1</b> dplyr 中的向量化</a></li>
<li class="chapter" data-level="3.2.2" data-path="sec-do-you-need.html"><a href="sec-do-you-need.html#section-3.2.2"><i class="fa fa-check"></i><b>3.2.2</b> 按列循环</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="4" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html"><i class="fa fa-check"></i><b>4</b> 加速</a><ul>
<li class="chapter" data-level="4.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1"><i class="fa fa-check"></i><b>4.1</b> 编写函数</a><ul>
<li class="chapter" data-level="4.1.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1.1"><i class="fa fa-check"></i><b>4.1.1</b> 减少重复</a></li>
<li class="chapter" data-level="4.1.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1.2"><i class="fa fa-check"></i><b>4.1.2</b> 引用函数的特殊之处在哪？</a></li>
<li class="chapter" data-level="4.1.3" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.1.3"><i class="fa fa-check"></i><b>4.1.3</b> 去引用</a></li>
<li class="chapter" data-level="4.1.4" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#-qq_show-"><i class="fa fa-check"></i><b>4.1.4</b> 通过 <code>qq_show()</code> 理解 <code>!!</code></a></li>
</ul></li>
<li class="chapter" data-level="4.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2"><i class="fa fa-check"></i><b>4.2</b> 引用和去引用</a><ul>
<li class="chapter" data-level="4.2.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.1"><i class="fa fa-check"></i><b>4.2.1</b> 第一步：抽取</a></li>
<li class="chapter" data-level="4.2.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.2"><i class="fa fa-check"></i><b>4.2.2</b> 第二步：引用</a></li>
<li class="chapter" data-level="4.2.3" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.3"><i class="fa fa-check"></i><b>4.2.3</b> 第三步：去引用</a></li>
<li class="chapter" data-level="4.2.4" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.2.4"><i class="fa fa-check"></i><b>4.2.4</b> 结果</a></li>
</ul></li>
<li class="chapter" data-level="4.3" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.3"><i class="fa fa-check"></i><b>4.3</b> 用字符串取代引用</a><ul>
<li class="chapter" data-level="4.3.1" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.3.1"><i class="fa fa-check"></i><b>4.3.1</b> 字符串</a></li>
<li class="chapter" data-level="4.3.2" data-path="sec-up-to-speed.html"><a href="sec-up-to-speed.html#section-4.3.2"><i class="fa fa-check"></i><b>4.3.2</b> 包含列名的字符串向量</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="5" data-path="multiple.html"><a href="multiple.html"><i class="fa fa-check"></i><b>5</b> Dealing with multiple arguments</a><ul>
<li class="chapter" data-level="5.1" data-path="multiple.html"><a href="multiple.html#the-...-argument"><i class="fa fa-check"></i><b>5.1</b> The <code>...</code> argument</a></li>
<li class="chapter" data-level="5.2" data-path="multiple.html"><a href="multiple.html#simple-forwarding-of-..."><i class="fa fa-check"></i><b>5.2</b> Simple forwarding of <code>...</code></a></li>
<li class="chapter" data-level="5.3" data-path="multiple.html"><a href="multiple.html#quote-multiple-arguments"><i class="fa fa-check"></i><b>5.3</b> Quote multiple arguments</a></li>
<li class="chapter" data-level="5.4" data-path="multiple.html"><a href="multiple.html#unquote-multiple-arguments"><i class="fa fa-check"></i><b>5.4</b> Unquote multiple arguments</a></li>
</ul></li>
<li class="chapter" data-level="6" data-path="modifying-inputs.html"><a href="modifying-inputs.html"><i class="fa fa-check"></i><b>6</b> Modifying inputs</a><ul>
<li class="chapter" data-level="6.1" data-path="modifying-inputs.html"><a href="modifying-inputs.html#modifying-names"><i class="fa fa-check"></i><b>6.1</b> Modifying names</a><ul>
<li class="chapter" data-level="6.1.1" data-path="modifying-inputs.html"><a href="modifying-inputs.html#default-argument-names"><i class="fa fa-check"></i><b>6.1.1</b> Default argument names</a></li>
<li class="chapter" data-level="6.1.2" data-path="modifying-inputs.html"><a href="modifying-inputs.html#unquoting-argument-names"><i class="fa fa-check"></i><b>6.1.2</b> Unquoting argument names</a></li>
<li class="chapter" data-level="6.1.3" data-path="modifying-inputs.html"><a href="modifying-inputs.html#prefixing-quoted-arguments"><i class="fa fa-check"></i><b>6.1.3</b> Prefixing quoted arguments</a></li>
</ul></li>
<li class="chapter" data-level="6.2" data-path="modifying-inputs.html"><a href="modifying-inputs.html#modifying-quoted-expressions"><i class="fa fa-check"></i><b>6.2</b> Modifying quoted expressions</a><ul>
<li class="chapter" data-level="6.2.1" data-path="modifying-inputs.html"><a href="modifying-inputs.html#expanding-quoted-expressions-with-expr"><i class="fa fa-check"></i><b>6.2.1</b> Expanding quoted expressions with <code>expr()</code></a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="7" data-path="glossary.html"><a href="glossary.html"><i class="fa fa-check"></i><b>7</b> Glossary</a><ul>
<li class="chapter" data-level="7.1" data-path="glossary.html"><a href="glossary.html#data-structures"><i class="fa fa-check"></i><b>7.1</b> Data structures</a><ul>
<li class="chapter" data-level="7.1.1" data-path="glossary.html"><a href="glossary.html#glossary-data-mask"><i class="fa fa-check"></i><b>7.1.1</b> TODO Data mask</a></li>
<li class="chapter" data-level="7.1.2" data-path="glossary.html"><a href="glossary.html#glossary-expr"><i class="fa fa-check"></i><b>7.1.2</b> Expression</a></li>
<li class="chapter" data-level="7.1.3" data-path="glossary.html"><a href="glossary.html#expression-base"><i class="fa fa-check"></i><b>7.1.3</b> Expression (base)</a></li>
<li class="chapter" data-level="7.1.4" data-path="glossary.html"><a href="glossary.html#glossary-sym"><i class="fa fa-check"></i><b>7.1.4</b> TODO Symbol</a></li>
</ul></li>
<li class="chapter" data-level="7.2" data-path="glossary.html"><a href="glossary.html#programming-concepts"><i class="fa fa-check"></i><b>7.2</b> Programming Concepts</a><ul>
<li class="chapter" data-level="7.2.1" data-path="glossary.html"><a href="glossary.html#glossary-constant-symbolic"><i class="fa fa-check"></i><b>7.2.1</b> Constant versus symbolic</a></li>
<li class="chapter" data-level="7.2.2" data-path="glossary.html"><a href="glossary.html#glossary-nse"><i class="fa fa-check"></i><b>7.2.2</b> TODO Non-Standard Evaluation (NSE)</a></li>
<li class="chapter" data-level="7.2.3" data-path="glossary.html"><a href="glossary.html#glossary-quotation-evaluation"><i class="fa fa-check"></i><b>7.2.3</b> TODO Quotation versus Evaluation</a></li>
<li class="chapter" data-level="7.2.4" data-path="glossary.html"><a href="glossary.html#glossary-qq"><i class="fa fa-check"></i><b>7.2.4</b> TODO Quasiquotation</a></li>
<li class="chapter" data-level="7.2.5" data-path="glossary.html"><a href="glossary.html#glossary-parse"><i class="fa fa-check"></i><b>7.2.5</b> TODO Parsing</a></li>
<li class="chapter" data-level="7.2.6" data-path="glossary.html"><a href="glossary.html#glossary-metaprogramming"><i class="fa fa-check"></i><b>7.2.6</b> TODO Metaprogramming</a></li>
</ul></li>
</ul></li>
<li class="part"><span><b>II Cookbooks</b></span></li>
<li class="chapter" data-level="8" data-path="dplyr.html"><a href="dplyr.html"><i class="fa fa-check"></i><b>8</b> dplyr</a><ul>
<li class="chapter" data-level="8.1" data-path="dplyr.html"><a href="dplyr.html#patterns-for-single-arguments"><i class="fa fa-check"></i><b>8.1</b> Patterns for single arguments</a><ul>
<li class="chapter" data-level="8.1.1" data-path="dplyr.html"><a href="dplyr.html#enquo-and---quote-and-unquote-arguments"><i class="fa fa-check"></i><b>8.1.1</b> <code>enquo()</code> and <code>!!</code> - Quote and unquote arguments</a></li>
<li class="chapter" data-level="8.1.2" data-path="dplyr.html"><a href="dplyr.html#quo_name---create-default-column-names"><i class="fa fa-check"></i><b>8.1.2</b> <code>quo_name()</code> - Create default column names</a></li>
<li class="chapter" data-level="8.1.3" data-path="dplyr.html"><a href="dplyr.html#and---unquote-column-names"><i class="fa fa-check"></i><b>8.1.3</b> <code>:=</code> and <code>!!</code> - Unquote column names</a></li>
</ul></li>
<li class="chapter" data-level="8.2" data-path="dplyr.html"><a href="dplyr.html#patterns-for-multiple-arguments"><i class="fa fa-check"></i><b>8.2</b> Patterns for multiple arguments</a><ul>
<li class="chapter" data-level="8.2.1" data-path="dplyr.html"><a href="dplyr.html#forward-multiple-arguments"><i class="fa fa-check"></i><b>8.2.1</b> <code>...</code> - Forward multiple arguments</a></li>
<li class="chapter" data-level="8.2.2" data-path="dplyr.html"><a href="dplyr.html#enquos-and---quote-and-unquote-multiple-arguments"><i class="fa fa-check"></i><b>8.2.2</b> <code>enquos()</code> and <code>!!!</code> - Quote and unquote multiple arguments</a></li>
<li class="chapter" data-level="8.2.3" data-path="dplyr.html"><a href="dplyr.html#expr---modify-quoted-arguments"><i class="fa fa-check"></i><b>8.2.3</b> <code>expr()</code> - Modify quoted arguments</a></li>
<li class="chapter" data-level="8.2.4" data-path="dplyr.html"><a href="dplyr.html#sec:external-quoting"><i class="fa fa-check"></i><b>8.2.4</b> <code>vars()</code> - Quote multiple arguments externally</a></li>
<li class="chapter" data-level="8.2.5" data-path="dplyr.html"><a href="dplyr.html#enquos.named-true---automatically-add-default-names"><i class="fa fa-check"></i><b>8.2.5</b> <code>enquos(.named = TRUE)</code> - Automatically add default names</a></li>
<li class="chapter" data-level="8.2.6" data-path="dplyr.html"><a href="dplyr.html#quos_auto_name---manually-add-default-names"><i class="fa fa-check"></i><b>8.2.6</b> <code>quos_auto_name()</code> - Manually add default names</a></li>
</ul></li>
<li class="chapter" data-level="8.3" data-path="dplyr.html"><a href="dplyr.html#select"><i class="fa fa-check"></i><b>8.3</b> <code>select()</code></a></li>
<li class="chapter" data-level="8.4" data-path="dplyr.html"><a href="dplyr.html#filter"><i class="fa fa-check"></i><b>8.4</b> <code>filter()</code></a></li>
<li class="chapter" data-level="8.5" data-path="dplyr.html"><a href="dplyr.html#case_when"><i class="fa fa-check"></i><b>8.5</b> <code>case_when()</code></a></li>
<li class="chapter" data-level="8.6" data-path="dplyr.html"><a href="dplyr.html#gotchas"><i class="fa fa-check"></i><b>8.6</b> Gotchas</a><ul>
<li class="chapter" data-level="8.6.1" data-path="dplyr.html"><a href="dplyr.html#nested-quoting-functions"><i class="fa fa-check"></i><b>8.6.1</b> Nested quoting functions</a></li>
</ul></li>
</ul></li>
<li class="chapter" data-level="9" data-path="ggplot2.html"><a href="ggplot2.html"><i class="fa fa-check"></i><b>9</b> ggplot2</a></li>
<li class="part"><span><b>III Going further</b></span></li>
<li class="chapter" data-level="10" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html"><i class="fa fa-check"></i><b>10</b> A rich toolbox</a><ul>
<li class="chapter" data-level="10.1" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-quote-expr-and-enexpr"><i class="fa fa-check"></i><b>10.1</b> TODO <code>quote()</code>, <code>expr()</code> and <code>enexpr()</code></a></li>
<li class="chapter" data-level="10.2" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-quo-and-enquo"><i class="fa fa-check"></i><b>10.2</b> TODO <code>quo()</code> and <code>enquo()</code></a></li>
<li class="chapter" data-level="10.3" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-vars-quos-and-enquos"><i class="fa fa-check"></i><b>10.3</b> TODO <code>vars()</code>, <code>quos()</code> and <code>enquos()</code></a></li>
<li class="chapter" data-level="10.4" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#toolbox-qq-show"><i class="fa fa-check"></i><b>10.4</b> TODO <code>qq_show()</code></a></li>
<li class="chapter" data-level="10.5" data-path="a-rich-toolbox.html"><a href="a-rich-toolbox.html#todo-sym-and-syms"><i class="fa fa-check"></i><b>10.5</b> TODO <code>sym()</code> and <code>syms()</code></a></li>
</ul></li>
<li class="chapter" data-level="11" data-path="creating-grammars.html"><a href="creating-grammars.html"><i class="fa fa-check"></i><b>11</b> Creating grammars</a></li>
</ul>

      </nav>
    </div>

    <div class="book-body">
      <div class="body-inner">
        <div class="book-header" role="navigation">
          <h1>
            <i class="fa fa-circle-o-notch fa-spin"></i><a href="./">Tidy evaluation</a>
          </h1>
        </div>

        <div class="page-wrapper" tabindex="-1" role="main">
          <div class="page-inner">

            <section class="normal" id="section-">
<div id="sec:why-how" class="section level1">
<h1><span class="header-section-number">2</span> 为什么使用以及怎么使用</h1>
<p>Tidy evaluation is a framework for metaprogramming in R, used throughout the tidyverse to implement data masking. Metaprogramming is about using a programming language to manipulate or modify its own code. This idea is used throughout the tidyverse to change the context of computation of certain pieces of R code.</p>
<p>Changing the context of evaluation is useful for four main purposes:</p>
<ul>
<li><p>To promote data frames to <strong>full blown scopes</strong>, where columns are exposed as named objects.</p></li>
<li><p>To execute your R code in a <strong>foreign environment</strong>. For instance, dbplyr translates ordinary dplyr pipelines to SQL queries.</p></li>
<li><p>To execute your R code with a more performant <strong>compiled language</strong>. For instance, the dplyr package uses C++ implementations for a certain set of mathematical expressions to avoid executing slower R code when possible<a href="#fn1" class="footnote-ref" id="fnref1"><sup>1</sup></a>.</p></li>
<li><p>To implement <strong>special rules</strong> for ordinary R operators. For instance, selection functions such as <code>dplyr::select()</code> or <code>tidyr::gather()</code> implement specific behaviours for <code>c()</code>, <code>:</code> and <code>-</code>.</p></li>
</ul>
<div id="section-2.1" class="section level2">
<h2><span class="header-section-number">2.1</span> 数据隐藏</h2>
<p>Of these goals, the promotion of data frames is the most important because data is often the most relevant context for data analysts. We believe that R and the tidyverse are <a href="https://principles.tidyverse.org/unifying-principles.html#human-centered">human-centered</a> in big part because the data frame is available for direct use in computations, without syntax and boilerplate getting in the way. Formulas for statistical models are a prime example of human-centered syntax in R. Data masking and special operator rules make model formulas an intuitive interface for model specification.</p>
<p>When the contents of the data frame are temporarily promoted as first class objects, we say the data <strong>masks</strong> the workspace:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">library</span>(<span class="st">&quot;dplyr&quot;</span>)

starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">filter</span>(
  height <span class="op">&lt;</span><span class="st"> </span><span class="dv">200</span>,
  gender <span class="op">==</span><span class="st"> &quot;male&quot;</span>
)</code></pre>
<p>Data masking is natural in R because it reduces boilerplate and results in code that maps more directly to how users think about data manipulation problems. Compare to the equivalent subsetting code where it is necessary to be explicit about where the columns come from:</p>
<pre class="sourceCode r"><code class="sourceCode r">starwars[starwars<span class="op">$</span>height <span class="op">&lt;</span><span class="st"> </span><span class="dv">200</span> <span class="op">&amp;</span><span class="st"> </span>starwars<span class="op">$</span>gender <span class="op">==</span><span class="st"> &quot;male&quot;</span>, ]</code></pre>
<p>Data masking is only possible because R allows suspending the normal flow of evaluation. If code was evaluated in the normal way, R would not be able to find the relevant columns for the computation. For instance, a normal function like <code>list()</code>, which has no concept of data masking, will give an error about object not found:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">list</span>(
  height <span class="op">&lt;</span><span class="st"> </span><span class="dv">200</span>,
  gender <span class="op">==</span><span class="st"> &quot;male&quot;</span>
)
<span class="co">#&gt; Error in eval(expr, envir, enclos): 找不到对象&#39;height&#39;</span></code></pre>
</div>
<div id="section-2.2" class="section level2">
<h2><span class="header-section-number">2.2</span> 引用代码</h2>
<p>In order to change the context, evaluation must first be suspended before being resumed in a different environment. The technical term for delaying code in this way is <strong>quoting</strong>. Tidyverse grammars quote the code supplied by users as arguments. They don’t get results of code but the quoted code itself, whose evaluation can be resumed later on in a data context. In a way, quoted code is like a blueprint for R computations. One important quoting function in dplyr is <code>vars()</code>. This function does nothing but return its arguments as blueprints to be interpreted later on by verbs like <code>summarise_at()</code>:</p>
<pre class="sourceCode r"><code class="sourceCode r">starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise_at</span>(<span class="kw">vars</span>(<span class="kw">ends_with</span>(<span class="st">&quot;color&quot;</span>)), n_distinct)
<span class="co">#&gt; # A tibble: 1 x 3</span>
<span class="co">#&gt;   hair_color skin_color eye_color</span>
<span class="co">#&gt;        &lt;int&gt;      &lt;int&gt;     &lt;int&gt;</span>
<span class="co">#&gt; 1         13         31        15</span></code></pre>
<p>If you call <code>vars()</code> alone, you get to see the blueprints! <a href="#fn2" class="footnote-ref" id="fnref2"><sup>2</sup></a></p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">vars</span>(
  <span class="kw">ends_with</span>(<span class="st">&quot;color&quot;</span>),
  height<span class="op">:</span>mass
)
<span class="co">#&gt; &lt;list_of&lt;quosure&gt;&gt;</span>
<span class="co">#&gt; </span>
<span class="co">#&gt; [[1]]</span>
<span class="co">#&gt; &lt;quosure&gt;</span>
<span class="co">#&gt; expr: ^ends_with(&quot;color&quot;)</span>
<span class="co">#&gt; env:  global</span>
<span class="co">#&gt; </span>
<span class="co">#&gt; [[2]]</span>
<span class="co">#&gt; &lt;quosure&gt;</span>
<span class="co">#&gt; expr: ^height:mass</span>
<span class="co">#&gt; env:  global</span></code></pre>
<p>The evaluation of an expression captured as a blueprint can be resumed at any time, possibly in a different context:</p>
<pre class="sourceCode r"><code class="sourceCode r">exprs &lt;-<span class="st"> </span><span class="kw">vars</span>(height <span class="op">/</span><span class="st"> </span><span class="dv">100</span>, mass <span class="op">+</span><span class="st"> </span><span class="dv">50</span>)

rlang<span class="op">::</span><span class="kw">eval_tidy</span>(exprs[[<span class="dv">1</span>]])
<span class="co">#&gt; Error in rlang::eval_tidy(exprs[[1]]): 找不到对象&#39;height&#39;</span>

rlang<span class="op">::</span><span class="kw">eval_tidy</span>(exprs[[<span class="dv">1</span>]], <span class="dt">data =</span> starwars)
<span class="co">#&gt;  [1] 1.72 1.67 0.96 2.02 1.50 1.78 1.65 0.97 1.83 1.82 1.88 1.80 2.28 1.80</span>
<span class="co">#&gt; [15] 1.73 1.75 1.70 1.80 0.66 1.70 1.83 2.00 1.90 1.77 1.75 1.80 1.50   NA</span>
<span class="co">#&gt; [29] 0.88 1.60 1.93 1.91 1.70 1.96 2.24 2.06 1.83 1.37 1.12 1.83 1.63 1.75</span>
<span class="co">#&gt; [43] 1.80 1.78 0.94 1.22 1.63 1.88 1.98 1.96 1.71 1.84 1.88 2.64 1.88 1.96</span>
<span class="co">#&gt; [57] 1.85 1.57 1.83 1.83 1.70 1.66 1.65 1.93 1.91 1.83 1.68 1.98 2.29 2.13</span>
<span class="co">#&gt; [71] 1.67 0.79 0.96 1.93 1.91 1.78 2.16 2.34 1.88 1.78 2.06   NA   NA   NA</span>
<span class="co">#&gt; [85]   NA   NA 1.65</span></code></pre>
<p>To sum up, the distinctive look and feel of data masking UIs requires suspending the normal evaluation of R code. Once captured as quoted code, it can be resumed in a different context. Unfortunately, the delaying of code makes it harder to program with data masking functions, and requires learning a bit of new theory and some new tools.</p>
</div>
<div id="section-2.3" class="section level2">
<h2><span class="header-section-number">2.3</span> 去引用代码</h2>
<p>Data masking functions prevent the normal evaluation of their arguments by quoting them. Once in possession of the blueprints of their arguments, a data mask is created and the evaluation is resumed in this new context. Unfortunately, delaying code in this way has a flip side. While it is natural to substitute <em>values</em> when you’re programming with normal functions using regular evaluation, it is harder to substitute <em>column names</em> in data masking functions that delay evaluation of your code. To make indirect references to columns, it is necessary to modify the quoted code <em>before</em> it gets evaluated. This is exactly what the <code>!!</code> operator, pronounced bang bang, is all about. It is a surgery operator for blueprints of R code.</p>
<p>In the world of normal functions, making indirect references to values is easy. Expressions that yield the same values can be freely interchanged, a property that is sometimes called <a href="https://en.wikipedia.org/wiki/Referential_transparency">referential transparency</a>. The following calls to <code>my_function()</code> all yield the same results because they were given the same value as inputs:</p>
<pre class="sourceCode r"><code class="sourceCode r">my_function &lt;-<span class="st"> </span><span class="cf">function</span>(x) x <span class="op">*</span><span class="st"> </span><span class="dv">100</span>

<span class="kw">my_function</span>(<span class="dv">6</span>)
<span class="co">#&gt; [1] 600</span>

<span class="kw">my_function</span>(<span class="dv">2</span> <span class="op">*</span><span class="st"> </span><span class="dv">3</span>)
<span class="co">#&gt; [1] 600</span>

a &lt;-<span class="st"> </span><span class="dv">2</span>
b &lt;-<span class="st"> </span><span class="dv">3</span>
<span class="kw">my_function</span>(a <span class="op">*</span><span class="st"> </span>b)
<span class="co">#&gt; [1] 600</span></code></pre>
<p>Because data masking functions evaluate their quoted arguments in a different context, they do not have this property:</p>
<pre class="sourceCode r"><code class="sourceCode r">starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">avg =</span> <span class="kw">mean</span>(height, <span class="dt">na.rm =</span> <span class="ot">TRUE</span>))
<span class="co">#&gt; # A tibble: 1 x 1</span>
<span class="co">#&gt;     avg</span>
<span class="co">#&gt;   &lt;dbl&gt;</span>
<span class="co">#&gt; 1  174.</span>

value &lt;-<span class="st"> </span><span class="kw">mean</span>(height, <span class="dt">na.rm =</span> <span class="ot">TRUE</span>)
<span class="co">#&gt; Error in mean(height, na.rm = TRUE): 找不到对象&#39;height&#39;</span>
starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">avg =</span> value)
<span class="co">#&gt; Error: 找不到对象&#39;value&#39;</span></code></pre>
<p>Storing a column name in a variable or passing one as a function argument requires the tidy eval operator <code>!!</code>. This special operator, only available in quoting functions, acts like a surgical operator for modifying blueprints. To understand what it does, it is best to see it in action. The <code>qq_show()</code> helper from rlang processes <code>!!</code> and prints the resulting blueprint of the computation. As you can observe, <code>!!</code> modifies the quoted code by inlining the value of its operand right into the blueprint:</p>
<pre class="sourceCode r"><code class="sourceCode r">x &lt;-<span class="st"> </span><span class="dv">1</span>

rlang<span class="op">::</span><span class="kw">qq_show</span>(
  starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">out =</span> x)
)
<span class="co">#&gt; starwars %&gt;% summarise(out = x)</span>

rlang<span class="op">::</span><span class="kw">qq_show</span>(
  starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">out =</span> <span class="op">!!</span>x)
)
<span class="co">#&gt; starwars %&gt;% summarise(out = 1)</span></code></pre>
<p>What would it take to create an indirect reference to a column name? Inlining the name as a string in the blueprint will not produce what you expect:</p>
<pre class="sourceCode r"><code class="sourceCode r">col &lt;-<span class="st"> &quot;height&quot;</span>

rlang<span class="op">::</span><span class="kw">qq_show</span>(
  starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">out =</span> <span class="kw">sum</span>(<span class="op">!!</span>col, <span class="dt">na.rm =</span> <span class="ot">TRUE</span>))
)
<span class="co">#&gt; starwars %&gt;% summarise(out = sum(&quot;height&quot;, na.rm = TRUE))</span></code></pre>
<p>This code amounts to taking the mean of a string, something that R will not be happy about:</p>
<pre class="sourceCode r"><code class="sourceCode r">starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">out =</span> <span class="kw">sum</span>(<span class="st">&quot;height&quot;</span>, <span class="dt">na.rm =</span> <span class="ot">TRUE</span>))
<span class="co">#&gt; Error in sum(&quot;height&quot;, na.rm = TRUE): &#39;type&#39;(character)参数不对</span></code></pre>
<p>To refer to column names inside a blueprint, we need to inline blueprint material. We need <strong>symbols</strong>:</p>
<pre class="sourceCode r"><code class="sourceCode r"><span class="kw">sym</span>(col)
<span class="co">#&gt; height</span></code></pre>
<p>Symbols are a special type of string that represent other objects. When a piece of R code is evaluated, every bare variable name is actually a symbol that represents some value, as defined in the current context. Let’s see what the modified blueprint looks like when we inline a symbol:</p>
<pre class="sourceCode r"><code class="sourceCode r">rlang<span class="op">::</span><span class="kw">qq_show</span>(
  starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">out =</span> <span class="kw">sum</span>(<span class="op">!!</span><span class="kw">sym</span>(col), <span class="dt">na.rm =</span> <span class="ot">TRUE</span>))
)
<span class="co">#&gt; starwars %&gt;% summarise(out = sum(height, na.rm = TRUE))</span></code></pre>
<p>Looks good! We’re now ready to actually run the dplyr pipeline with an indirect reference:</p>
<pre class="sourceCode r"><code class="sourceCode r">starwars <span class="op">%&gt;%</span><span class="st"> </span><span class="kw">summarise</span>(<span class="dt">out =</span> <span class="kw">sum</span>(<span class="op">!!</span><span class="kw">sym</span>(col), <span class="dt">na.rm =</span> <span class="ot">TRUE</span>))
<span class="co">#&gt; # A tibble: 1 x 1</span>
<span class="co">#&gt;     out</span>
<span class="co">#&gt;   &lt;int&gt;</span>
<span class="co">#&gt; 1 14123</span></code></pre>
<p>There were two necessary steps to create an indirect reference and properly modify the summarising code:</p>
<ul>
<li>We first created a piece of blueprint (a symbol) with <code>sym()</code>.</li>
<li>We used <code>!!</code> to insert it in the blueprint captured by <code>summarise()</code>.</li>
</ul>
<p>We call the combination of these two steps the <strong>quote and unquote</strong> pattern. This pattern is the heart of programming with tidy eval functions. We quote an expression and unquote it in another quoted expression. In other words, we create or capture a piece of blueprint, and insert it in another blueprint just before it’s captured by a data masking function. This process is also called <strong>interpolation</strong>.</p>
<p>Most of the time though, we don’t need to create blueprints manually. We’ll get them by quoting the arguments supplied by users. This gives your functions the same usage and feel as tidyverse verbs.</p>
</div>
</div>
<div class="footnotes">
<hr />
<ol start="1">
<li id="fn1"><p>The data.table package uses different metaprogramming tools than tidy eval for the same purpose. Certain expressions are executed in C to perform efficient data transformations.<a href="sec-why-how.html#fnref1" class="footnote-back">↩</a></p></li>
<li id="fn2"><p>As you can see, these blueprints are also called <strong>quosures</strong>. These are special types of <a href="glossary.html#glossary-expr">expressions</a> that keep track of the current context, or <a href="#glossary-env">environment</a>.<a href="sec-why-how.html#fnref2" class="footnote-back">↩</a></p></li>
</ol>
</div>
            </section>

          </div>
        </div>
      </div>
<a href="section-1.html" class="navigation navigation-prev " aria-label="Previous page"><i class="fa fa-angle-left"></i></a>
<a href="sec-do-you-need.html" class="navigation navigation-next " aria-label="Next page"><i class="fa fa-angle-right"></i></a>
    </div>
  </div>
<script src="libs/gitbook-2.6.7/js/app.min.js"></script>
<script src="libs/gitbook-2.6.7/js/lunr.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-search.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-sharing.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-fontsettings.js"></script>
<script src="libs/gitbook-2.6.7/js/plugin-bookdown.js"></script>
<script src="libs/gitbook-2.6.7/js/jquery.highlight.js"></script>
<script>
gitbook.require(["gitbook"], function(gitbook) {
gitbook.start({
"sharing": {
"github": true,
"facebook": false,
"twitter": false,
"google": false,
"linkedin": false,
"weibo": false,
"instapaper": false,
"vk": false,
"all": ["facebook", "google", "twitter", "linkedin", "weibo", "instapaper"]
},
"fontsettings": {
"theme": "white",
"family": "sans",
"size": 2
},
"edit": {
"link": "https://github.com/ShixiangWang/tidyeval/edit/master/introduction.Rmd",
"text": "Edit"
},
"history": {
"link": null,
"text": null
},
"download": null,
"toc": {
"collapse": "section"
}
});
});
</script>

</body>

</html>
